#include "PlayMangent.h"
#include "Audio/QtAudioOutputStrategy.h"


PlayMangent::PlayMangent():m_signal_received(false),m_play_status(PlayStatus::IDLING),
m_minSpeed(0.5), m_maxSpeed(10.0), m_currentplaybackRate(1.0), m_variableSpeedEnabled(false)
#if __cplusplus >= 202002L
,sema(0),sem_decoder(2)
#endif
{
  //初始化packet管理类
  m_packet_manager.init();
  // 创建AVSync实例
  m_audio_decoder = std::make_unique<AudioDecoder>();
  m_video_decoder = std::make_unique<VideoDecoder>();
  //初始化音视频同步类
  AVSync::getInstance().init();
  //use to control the playback thread
  m_playback_thread = std::make_shared<std::thread>(&PlayMangent::playback_thread_func, this);
}
PlayMangent::~PlayMangent()
{
   // 如果线程可 join，等待它结束
   if (m_playback_thread && m_playback_thread->joinable())
   {
       m_playback_thread->join();
   }
}
bool PlayMangent::addfile(const std::string &  filename)
{
  FileMangent::get_instance().addfile(filename);
  return true;
}
bool PlayMangent::play(){
    std::unique_lock<std::mutex> lock(mutex_thread);
    std::cout << "receive play signal ,and now is:"<<playStatusToString(m_play_status) << std::endl;
    //如果是停止状态，就开始播放
    if(m_play_status == PlayStatus::IDLING){
        //check file is empty
        if(FileMangent::get_instance().getfilecount()== 0 ){
            std::cout<<"file list is empty"<<std::endl;
            return false;
        }
        std::cout<<"first play"<<std::endl;
        m_play_status = PlayStatus::PLAYING;
        m_signal_received.store(true);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::cout<<"set m_signal_received:"<<m_signal_received<<std::endl;
        lock.unlock();
        m_cond_var.notify_one();

        notifyPlaybackStarted();
        return true;
    }
    else if(m_play_status == PlayStatus::STOPPED){
        std::cout<<"play start"<<std::endl;
        m_play_status = PlayStatus::PLAYING;
        m_signal_received.store(true);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::cout<<"set m_signal_received:"<<m_signal_received<<std::endl;
        FileMangent::get_instance().resetAndReadFrames();
        lock.unlock();
        m_cond_var.notify_one();
        notifyPlaybackStarted();
        return true;
    }
    //如果是暂停状态，就继续播放
    else if(m_play_status == PlayStatus::PAUSED){
        std::cout<<"play continue"<<std::endl;
        m_play_status = PlayStatus::PLAYING;
#if __cplusplus >= 202002L
        sema.release();  // 增加信号量，唤醒worker线程
#endif
        return true;
    }
    else if(m_play_status == PlayStatus::PLAYING){
        std::cout<<"now is playing"<<std::endl;
        return true;
    }
    else if(m_play_status == PlayStatus::BUSY){
        std::cout<<"play busy"<<std::endl;
        return true;
    }
    else{
        std::cout<<"play error"<<std::endl;
        return false;
    }
    return true;
}
bool PlayMangent::stop(){
    std::unique_lock<std::mutex> lock(mutex_thread);
    std::cout << "receive stop signal ,and now is:"<<playStatusToString(m_play_status) << std::endl;
    if(m_play_status == PlayStatus::PLAYING || m_play_status == PlayStatus::PAUSED || m_play_status == PlayStatus::BUSY){
        m_play_status = PlayStatus::STOPPED;
        std::cout<<"play stop"<<std::endl;
        notifyPlaybackStopped();

        AVSync::getInstance().stop();
        return true;
    }
    else{

        return false;
    }
    return true;
}
bool PlayMangent::pause(){
    std::unique_lock<std::mutex> lock(mutex_thread);
    std::cout << "receive pause signal ,and now is:"<<playStatusToString(m_play_status) << std::endl;
    if(m_play_status == PlayStatus::PLAYING || m_play_status == PlayStatus::BUSY){
        m_play_status = PlayStatus::PAUSED;
        std::cout<<"play pause"<<std::endl;
        return true;
    }
    std::cout<<"play pause error"<<std::endl;
    return true;
}

bool PlayMangent::play_next(){
    std::unique_lock<std::mutex> lock(mutex_thread);
    std::cout << "receive play next signal ,and now is:"<<playStatusToString(m_play_status) << std::endl;
    std::cout<<"play next"<<std::endl;
    if(m_play_status == PlayStatus::PLAYING || m_play_status == PlayStatus::PAUSED || m_play_status == PlayStatus::BUSY){
        m_play_status = PlayStatus::STOPPED;
        return true;
    }
    return true;
}
bool PlayMangent::play_previous(){
    std::unique_lock<std::mutex> lock(mutex_thread);
    std::cout << "receive play previous signal ,and now is:"<<playStatusToString(m_play_status) << std::endl;
    std::cout<<"play previous"<<std::endl;
    if(m_play_status == PlayStatus::PLAYING || m_play_status == PlayStatus::PAUSED || m_play_status == PlayStatus::BUSY){
        m_play_status = PlayStatus::STOPPED;
        return true;
    }
    return true;
}
bool PlayMangent::changedPlaybackspeed(float seed){
    std::unique_lock<std::mutex> lock(mutex_thread);
    std::cout << "receive changedPlaybackspeed signal ,and now is:"<<playStatusToString(m_play_status) << std::endl;

    return true;
}
bool PlayMangent::check_codec_ctx(AVCodecContext* audio_codec_ctx, AVCodecContext* video_codec_ctx) {
    if (audio_codec_ctx && video_codec_ctx) {
        // 如果audio_codec_ctx和video_codec_ctx都不为空，则继续执行
        //        std::cout << "codec_ctx init successfully" << std::endl;
        // 进一步检查audio_codec_ctx和video_codec_ctx指向的对象是否有效
        if (audio_codec_ctx->codec_id != AV_CODEC_ID_NONE && video_codec_ctx->codec_id != AV_CODEC_ID_NONE) {
            //            std::cout << "codec_ctx objects are valid" << std::endl;
        } else {
            std::cout << "codec_ctx objects are not valid" << std::endl;
            return false;
        }
    } else {
        std::cout << "codec_ctx init failed" << std::endl;
        return false;
        // 如果audio_codec_ctx或video_codec_ctx中至少有一个为空，则处理错误或执行其他操作
    }
    return true;
}

// 播放线程函数
void PlayMangent::playback_thread_func()
{
    // 获取文件管理器实例
    FileMangent& file_mangent = FileMangent::get_instance();


    while(true)
    {
        // 等待信号
        std::cout << "playback_thread_func waiting for signal" << std::endl;

        std::unique_lock<std::mutex> lock(mutex_thread);
        m_cond_var.wait(lock, [this] { return m_signal_received.load(); });
        m_signal_received.store(false);
        m_play_status = PlayStatus::BUSY;
//        std::cout << "playback_thread_func woke up, m_signal_received: " << m_signal_received <<"-"<<playStatusToString(m_play_status)<< std::endl;
        {//new play cycle
            auto fileinfo = file_mangent.getFileInfo(file_mangent.getcurrentfile());
            const AVFormatContextWrapper::AVCodecContextPtr& audio_codec_ctx = file_mangent.get_audio_codec_context();
            const AVFormatContextWrapper::AVCodecContextPtr& video_codec_ctx = file_mangent.get_video_codec_context();
            AVSync::getInstance().setAudioSyncInfo(audio_codec_ctx.get(), fileinfo);
            AVSync::getInstance().setVideoSyncInfo(video_codec_ctx.get(), fileinfo);
            AVSync::getInstance().init();

            DecoderThread<VideoDecoder> video_decoder_thread(
                m_video_decoder,
                file_mangent.get_video_queue(),
                [&]() {
                    m_video_decoder->release();
                    m_video_decoder->init(file_mangent.get_video_codec_context());
                    m_video_decoder->adjustPlaybackSpeed(100);
                }
             );
            video_decoder_thread.start();

            DecoderThread<AudioDecoder> audio_decoder_thread(
                m_audio_decoder,
                file_mangent.get_audio_queue(),
                [&]() {
                    m_audio_decoder->release();
                    m_audio_decoder->init(file_mangent.get_audio_codec_context());
                }
            );
            audio_decoder_thread.start();

            if(m_play_status == PlayStatus::BUSY){
                m_play_status = PlayStatus::PLAYING;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(5000));

            lock.unlock();

            main_play_func(fileinfo);
      
            if(m_play_status == PlayStatus::PLAYING){
                m_play_status = PlayStatus::STOPPED;
            }
            video_decoder_thread.stop();
            audio_decoder_thread.stop();
        }//play loop
    }//main thread loop
//PlayEnd:
 //
    // 清理操作，例如释放解码器资源
}
void PlayMangent::playVideo(int& milliseconds_diff) {
    std::chrono::milliseconds duration;
    while (true) {
        AVSync::getInstance().send_video_frame();
        {
            std::lock_guard<std::mutex> lock(m_sync_mutex);
            duration = std::chrono::milliseconds(milliseconds_diff);
        }
        //lock_guard end
        if(duration.count() == 0){
            
        }
        else{
            std::this_thread::sleep_for(duration);
        }
    }
}

//main_play_func
int PlayMangent::main_play_func(const FileInfo& fileinfo)
{
  int milliseconds_diff = 0;
  int sync_ret = -1;
  std::thread video_thread(&PlayMangent::playVideo, this, std::ref(milliseconds_diff));


  QtAudioOutputStrategy m_qt_audio_output_strategy;
  m_qt_audio_output_strategy.init();

  auto audio_delay = std::chrono::duration<int, std::micro>(static_cast<int>(fileinfo.audio_type_time_base * 1e6));
    //int delay_milliseconds = static_cast<int>(std::round(fileinfo.audio_type_time_base  * 1000));
	int audio_nb_samples = 0;
  while(true)
  {
//check play status
    if(m_play_status == PlayStatus::PAUSED){
        std::cout<<"playback_thread_func: paused"<<std::endl;
#if __cplusplus >= 202002L
        sema.acquire();  // 等待信号量
#endif
        std::cout<<"playback_thread_func: paused end"<<std::endl;
                    //  continue;
    }
    else if (m_play_status == PlayStatus::STOPPED){
        std::cout<<"playback_thread_func: stopped"<<std::endl;
        return 0;
    }
//check play status end
    {
        std::lock_guard<std::mutex> lock(m_sync_mutex);
        sync_ret = AVSync::getInstance().check_sync_status(milliseconds_diff);
    }//lock_guard end
	if(sync_ret == -1){
        if(AVSync::getInstance().getSyncStatus() == AVSync::SyncStatus::Busy){
            std::cout<<"sync busy"<<std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            continue;
        }
        else{
            std::cout<<"sync error"<<std::endl;
            return -1;
        }
    }
    auto  decodedData = AVSync::getInstance().getSyncedData<std::queue<float>>(audio_nb_samples);
  //   std::cout << "Info: Retrieved decoded audio data. Size: " << decodedData.size() << std::endl;

    // Pass decoded audio data to QtAudioOutputStrategy class
    m_qt_audio_output_strategy.dataReady(decodedData);

    // 以音频时间基准为基础做播放
    //std::this_thread::sleep_for(std::chrono::milliseconds(delay_milliseconds));
    std::this_thread::sleep_for(audio_delay*audio_nb_samples);
		//cout audio_delay and base on audio_nb_samples
    //	std::cout << "audio_delay: " << audio_delay.count() << " audio_nb_samples: " << audio_nb_samples << std::endl;
  }
}
